<template>
  <client-only>
    <component v-if="column.search?.el" :is="setCom" v-bind="{ ...handleSearchProps, ...placeholder }"
      v-model.trim="searchParam[column.search.key ?? handleProp(column.prop!)]"
      :data="column.search?.el === 'tree-select' ? columnEnum : []"
      :options="['cascader', 'select-v2'].includes(column.search?.el) ? columnEnum : []" :clearable="clearable"
      @change="emitChangeFn">
      <template #default="{ data }" v-if="column.search.el === 'cascader'">
        <span>{{ data[fieldNames.label] }}</span>
      </template>
      <template v-if="column.search.el === 'select'">
        <client-only>
          <component :is="ElOption" v-for="(col, index) in columnEnum" :key="index" :label="col[fieldNames.label]"
            :value="col[fieldNames.value]"></component>
        </client-only>
      </template>
      <slot v-else></slot>
    </component>
  </client-only>
</template>

<script setup lang="ts" name="SearchFormItem">
import { handleProp } from "@/utils";
import { ElInput, ElSelect, ElOption, ElDatePicker, ElCascader, ElSelectV2 } from "element-plus";
// 默认值
const props = defineProps({
  column: {
    type: Object,
    default: () => { }
  },
  searchParam: {
    type: Object,
    default: () => { }
  },
})
const setCom = computed(() => {
  let com = ''
  switch (props.column.search.el) {
    case 'input':
      com = ElInput
      break;
    case 'select':
      com = ElSelect
      break;
    case 'date-picker':
      com = ElDatePicker
      break;
    case 'cascader':
      com = ElCascader
      break;
    case 'select-v2':
      com = ElSelectV2
      break;
    default:
      com = ElInput
      break;
  }
  return com
})
// 判断 fieldNames 设置 label && value && children 的 key 值
const fieldNames = computed(() => {
  return {
    label: props.column.fieldNames?.label ?? "label",
    value: props.column.fieldNames?.value ?? "value",
    children: props.column.fieldNames?.children ?? "children",
  };
});

// 接收 enumMap (el 为 select-v2 需单独处理 enumData)
const enumMap = inject("enumMap", ref(new Map()));
const columnEnum = computed(() => {
  let enumData = enumMap.value.get(props.column.prop);
  if (!enumData) return [];
  if (props.column.search?.el === "select-v2" && props.column.fieldNames) {
    enumData = enumData.map((item: { [key: string]: any }) => {
      return { ...item, label: item[fieldNames.value.label], value: item[fieldNames.value.value] };
    });
  }
  return enumData;
});

// 处理透传的 searchProps (el 为 tree-select、cascader 的时候需要给下默认 label && value && children)
const handleSearchProps = computed(() => {
  const label = fieldNames.value.label;
  const value = fieldNames.value.value;
  const children = fieldNames.value.children;
  const searchEl = props.column.search?.el;
  let searchProps = props.column.search?.props ?? {};
  if (searchEl === "tree-select") {
    searchProps = { ...searchProps, props: { ...searchProps.props, label, children }, nodeKey: value };
  }
  if (searchEl === "cascader") {
    searchProps = { ...searchProps, props: { ...searchProps.props, label, value, children } };
  }

  return searchProps;
});

// 处理默认 placeholder
const placeholder = computed(() => {
  const search = props.column.search;
  if (["datetimerange", "daterange", "monthrange"].includes(search?.props?.type) || search?.props?.isRange) {
    return { rangeSeparator: "至", startPlaceholder: "开始时间", endPlaceholder: "结束时间" };
  }
  const placeholder =
    search?.props?.placeholder ?? (search?.el.includes("input") ? "请输入" : "请选择") + (props.column.label || "");
  return { placeholder };
});

// 是否有清除按钮 (当搜索项有默认值时，清除按钮不显示)
const clearable = computed(() => {
  const search = props.column.search;
  return search?.props?.clearable ?? (search?.defaultValue == null || search?.defaultValue == undefined);
});

// 修改改立刻搜索
const emitChangeFn = () => {
  let fieldCover = props.column.search?.fieldCover;
  if (fieldCover) {
    fieldCover.target.forEach((item, index) => {
      props.searchParam[item] = props.searchParam[fieldCover.source][index];
    });
    emit("change");
  }
};

const emit = defineEmits(["change"]);
</script>
